package com.az.miaoauth.service.impl;


import com.az.miaoapi.exception.BaseException;
import com.az.miaoapi.response.ResponseCode;
import com.az.miaoauth.domain.dto.EmailCodeDto;
import com.az.miaoauth.domain.dto.UserCodeDto;
import com.az.miaoauth.domain.po.TheUser;
import com.az.miaoauth.domain.vo.RegisterTokenVo;
import com.az.miaoauth.domain.vo.TokenVo;
import com.az.miaoauth.mapper.TheUserMapper;
import com.az.miaoauth.service.EmailService;
import com.az.miaoauth.service.RegisterService;
import com.az.miaoauth.util.LoginUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.retry.annotation.Retryable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import java.util.Optional;

@Service
@RequiredArgsConstructor
public class RegisterServiceImpl extends ServiceImpl<TheUserMapper, TheUser> implements RegisterService {

    private final TheUserMapper theUserMapper;
    private final PasswordEncoder passwordEncoder;
    private final EmailService emailService;
    private final RedisTemplate<String, Object> redisTemplate;

    @Override
    @Retryable(noRetryFor = BaseException.class)
    public RegisterTokenVo registerStudent(UserCodeDto userCodeDto) {

        Optional.ofNullable(theUserMapper.selectOne(Wrappers.lambdaQuery(TheUser.class)
                        .eq(TheUser::getUsername, userCodeDto.getUsername())))
                .ifPresent(user -> {throw new BaseException(ResponseCode.USERNAME_REPEAT);});

        RegisterTokenVo registerTokenVo = new RegisterTokenVo();
        registerTokenVo.setStatus(1);

        emailService.bindEmailCode(new EmailCodeDto(userCodeDto.getEmail(), userCodeDto.getCode()));

        TheUser user = Optional.ofNullable(theUserMapper.selectOne(Wrappers.lambdaQuery(TheUser.class)
                        .eq(TheUser::getEmail, userCodeDto.getEmail())))
                .orElseGet(() -> {
                    TheUser theUser = new TheUser();
                    theUser.setUsername(userCodeDto.getUsername());
                    theUser.setEmail(userCodeDto.getEmail());
                    theUser.setPassword(passwordEncoder.encode(userCodeDto.getPassword()));
                    theUser.setRole("student");
                    registerTokenVo.setStatus(0);
                    theUserMapper.insert(theUser);
                    return theUser;
                });

        TokenVo login = LoginUtil.login(user, redisTemplate);
        registerTokenVo.setToken(login.getToken());
        registerTokenVo.setRole(login.getRole());
        registerTokenVo.setUsername(user.getUsername());
        registerTokenVo.setRole(user.getRole());
        return registerTokenVo;
    }
}
